package com.jlf.core.server;

import com.jlf.core.annotation.server.add.AddAfterProcessor;
import com.jlf.core.annotation.server.add.AddPostProcessor;
import com.jlf.core.annotation.server.add.AddPreProcessor;
import com.jlf.core.annotation.server.add.AddProcessor;
import com.jlf.core.annotation.server.delete.DeleteAfterProcessor;
import com.jlf.core.annotation.server.delete.DeletePostProcessor;
import com.jlf.core.annotation.server.delete.DeletePreProcessor;
import com.jlf.core.annotation.server.delete.DeleteProcessor;
import com.jlf.core.annotation.server.edit.EditAfterProcessor;
import com.jlf.core.annotation.server.edit.EditPostProcessor;
import com.jlf.core.annotation.server.edit.EditPreProcessor;
import com.jlf.core.annotation.server.edit.EditProcessor;
import com.jlf.core.annotation.server.view.LoadProcessor;
import com.jlf.core.annotation.server.view.QueryProcessor;
import com.jlf.core.annotation.server.view.ViewProcessor;
import com.jlf.core.domain._SimpleDO;
import com.jlf.core.server.entity.AddRecordWrapper;
import com.jlf.core.server.entity.EditRecordWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.MalformedParametersException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 简单服务的处理器
 *
 * @author wujr
 * 2023/7/5
 * @version 1.0
 * 【变更历史】
 * [wujr 2023/7/5 1.0 新增]
 */
@Slf4j
@RequiredArgsConstructor
public class SimpleProcessor {
    class _ProcessorWrapper implements Comparable<_ProcessorWrapper>{
        Method method;
        public int order;
        boolean wrapper = false;

        _ProcessorWrapper(Method method, int order){
            this.method = method;
            this.order = order;
            checkWrapper();
        }
        void checkWrapper(){
            int parameterCount = this.method.getParameterCount();
            if (parameterCount != 1){
                log.error("处理器方法参数错误，处理器仅支持一个参数");
                throw new MalformedParametersException();
            }
            Class<?>[] parameterTypes = this.method.getParameterTypes();
            Class<?> recordParameterType = parameterTypes[0];
            if (AddRecordWrapper.class.isAssignableFrom(recordParameterType)){
                wrapper = true;
            }else if (EditRecordWrapper.class.isAssignableFrom(recordParameterType)){
                wrapper = true;
            }
        }
        @Override
        public int compareTo(_ProcessorWrapper record){
            return this.order - record.order;
        }
    }
    /**
     * 新增领域的前置处理
     * 在该方法中不进行数据的变更，不需要开启事务
     * 被注解：{@link AddPreProcessor} 标注的函数
     */
    private final List<_ProcessorWrapper> _addPreProcessor = new ArrayList<>();
    /**
     * 新增领域的事务处理
     * 被注解：{@link AddProcessor} 标注的函数
     */
    private Method _addProcessor;
    /**
     * 新增领域的后置处理
     * 在该方法中可以进行数据的变更
     * 被注解：{@link AddPostProcessor} 标注的函数
     */
    private final List<_ProcessorWrapper> _addPostProcessor = new ArrayList<>();
    /**
     * 新增的收尾处理，事务已经生效
     */
    private final List<_ProcessorWrapper> _addAfterProcessor = new ArrayList<>();

    /**
     * 编辑领域的前置处理
     * 在该方法中不进行数据的变更，不需要开启事务
     * 被注解：{@link EditPreProcessor} 标注的函数
     */
    private final List<_ProcessorWrapper> _editPreProcessor = new ArrayList<>();
    /**
     * 编辑领域的事务处理
     * 被注解：{@link EditProcessor} 标注的函数
     */
    private Method _editProcessor;
    /**
     * 编辑领域的后置处理
     * 在该方法中可以进行数据的变更
     * 被注解：{@link EditPostProcessor} 标注的函数
     */
    private final List<_ProcessorWrapper> _editPostProcessor = new ArrayList<>();
    /**
     * 编辑的收尾处理，事务已经生效
     * 被注解：{@link EditAfterProcessor} 标准的函数
     */
    private final List<_ProcessorWrapper> _editAfterProcessor = new ArrayList<>();
    /**
     * 加载领域对象的处理器
     */
    private Method _loadProcessor;
    /**
     * 查询领域的处理器
     */
    private Method _queryProcessor;
    /**
     * 详情领域的处理器
     */
    private Method _viewProcessor;

    /**
     * 删除领域的前置处理
     * 在该方法中不进行数据的变更，不需要开启事务
     * 被注解：{@link DeletePreProcessor} 标注的函数
     */
    private final List<_ProcessorWrapper> _deletePreProcessor = new ArrayList<>();
    /**
     * 删除领域的事务处理
     * 被注解：{@link DeleteProcessor} 标注的函数
     */
    private Method _deleteProcessor;
    /**
     * 删除领域的后置处理
     * 在该方法中可以进行数据的变更
     * 被注解：{@link DeletePostProcessor} 标注的函数
     */
    private final List<_ProcessorWrapper> _deletePostProcessor = new ArrayList<>();
    /**
     * 删除的收尾处理，事务已经生效
     * 被注解：{@link DeleteAfterProcessor} 标注的函数
     */
    private final List<_ProcessorWrapper> _deleteAfterProcessor = new ArrayList<>();
    /**
     * 服务的bean对象
     */
    private final Object _bean;
    private final Class<?> _class;

    public SimpleProcessor(Class<?> _class, Object bean){
        this._bean = bean;
        this._class = _class;
        scanProcessor();
    }
    protected void scanProcessor(){
        // 扫码服务bean中的各种处理器
        Method[] methods = _class.getMethods();
        for (Method method : methods){
            if (method.isAnnotationPresent(AddPreProcessor.class)){
                AddPreProcessor annotation = method.getAnnotation(AddPreProcessor.class);
                _addPreProcessor.add(new _ProcessorWrapper(method, annotation.order()));
            }
            if (method.isAnnotationPresent(AddProcessor.class)){
                _addProcessor = method;
            }
            if (method.isAnnotationPresent(AddPostProcessor.class)){
                AddPostProcessor annotation = method.getAnnotation(AddPostProcessor.class);
                _addPostProcessor.add(new _ProcessorWrapper(method, annotation.order()));
            }
            if (method.isAnnotationPresent(AddAfterProcessor.class)){
                AddAfterProcessor annotation = method.getAnnotation(AddAfterProcessor.class);
                _addAfterProcessor.add(new _ProcessorWrapper(method, annotation.order()));
            }
            if (method.isAnnotationPresent(EditPostProcessor.class)){
                EditPostProcessor annotation = method.getAnnotation(EditPostProcessor.class);
                _editPostProcessor.add(new _ProcessorWrapper(method, annotation.order()));
            }
            if (method.isAnnotationPresent(EditPreProcessor.class)){
                EditPreProcessor annotation = method.getAnnotation(EditPreProcessor.class);
                _editPreProcessor.add(new _ProcessorWrapper(method, annotation.order()));
            }
            if (method.isAnnotationPresent(EditProcessor.class)){
                _editProcessor = method;
            }
            if (method.isAnnotationPresent(EditAfterProcessor.class)) {
                EditAfterProcessor annotation = method.getAnnotation(EditAfterProcessor.class);
                _editAfterProcessor.add(new _ProcessorWrapper(method, annotation.order()));
            }
            if (method.isAnnotationPresent(DeletePreProcessor.class)) {
                DeletePreProcessor annotation = method.getAnnotation(DeletePreProcessor.class);
                _deletePreProcessor.add(new _ProcessorWrapper(method, annotation.order()));
            }
            if (method.isAnnotationPresent(DeleteProcessor.class)) {
                _deleteProcessor = method;
            }else if (method.isAnnotationPresent(DeletePostProcessor.class)) {
                DeletePostProcessor annotation = method.getAnnotation(DeletePostProcessor.class);
                _deletePostProcessor.add(new _ProcessorWrapper(method, annotation.order()));
            }
            if (method.isAnnotationPresent(DeleteAfterProcessor.class)){
                DeleteAfterProcessor annotation = method.getAnnotation(DeleteAfterProcessor.class);
                _deleteAfterProcessor.add(new _ProcessorWrapper(method, annotation.order()));
            }
            if (method.isAnnotationPresent(LoadProcessor.class)){
                _loadProcessor = method;
            }
            if (method.isAnnotationPresent(QueryProcessor.class)){
                _queryProcessor = method;
            }
            if (method.isAnnotationPresent(ViewProcessor.class)){
                _viewProcessor = method;
            }
        }

        Collections.sort(_addPreProcessor);
        Collections.sort(_addPostProcessor);
        Collections.sort(_addAfterProcessor);
        Collections.sort(_editPostProcessor);
        Collections.sort(_editPreProcessor);
        Collections.sort(_editAfterProcessor);
        Collections.sort(_deletePreProcessor);
        Collections.sort(_deletePostProcessor);
        Collections.sort(_deleteAfterProcessor);
    }

    public <T extends _SimpleDO<T>> void preAdd(T record) throws Exception{
        if (CollectionUtils.isEmpty(_addPreProcessor)){
            // 没有定义新增的前置处理器
            return;
        }
        for (_ProcessorWrapper processor : _addPostProcessor){
            if (processor.wrapper){
                continue;
            }
            process(processor, record);
        }
    }
    public <T extends _SimpleDO<T>> void preAdd(AddRecordWrapper<T> record) throws Exception{
        if (CollectionUtils.isEmpty(_addPreProcessor)){
            // 没有定义新增的前置处理器
            return;
        }
        for (_ProcessorWrapper processor : _addPostProcessor){
            if (!processor.wrapper){
                continue;
            }
            process(processor, record);
        }
    }
    public <T extends _SimpleDO<T>> void postAdd(T record) throws Exception{
        if (CollectionUtils.isEmpty(_addPostProcessor)){
            // 没有定义新增的前置处理器
            return;
        }
        for (_ProcessorWrapper processor : _addPostProcessor){
            if (processor.wrapper){
                continue;
            }
            process(processor, record);
        }
    }
    public <T extends _SimpleDO<T>> void postAdd(AddRecordWrapper<T> record) throws Exception{
        if (CollectionUtils.isEmpty(_addPostProcessor)){
            // 没有定义新增的前置处理器
            return;
        }
        for (_ProcessorWrapper processor : _addPostProcessor){
            if (!processor.wrapper){
                continue;
            }
            process(processor, record);
        }
    }
    public <T extends _SimpleDO<T>> void afterAdd(T record, boolean succeed) throws Exception{
        if (CollectionUtils.isEmpty(_addPostProcessor)){
            // 没有定义新增的前置处理器
            return;
        }
        for (_ProcessorWrapper processor : _addPostProcessor){
            if (processor.wrapper){
                continue;
            }
            process(processor, record, succeed);
        }
    }
    public <T extends _SimpleDO<T>> void afterAdd(AddRecordWrapper<T> record, boolean succeed) throws Exception{
        if (CollectionUtils.isEmpty(_addPostProcessor)){
            // 没有定义新增的前置处理器
            return;
        }
        for (_ProcessorWrapper processor : _addPostProcessor){
            if (!processor.wrapper){
                continue;
            }
            process(processor, record, succeed);
        }
    }

    void process(_ProcessorWrapper processor, Object record) throws Exception{
        try {
            processor.method.invoke(_bean, record);
        }catch (Exception e){
            // 对异常进行转义处理
            if (e instanceof InvocationTargetException){
                Throwable throwable = e.getCause();
                if (throwable instanceof Exception){
                    throw (Exception)throwable;
                }
            }
            throw e;
        }
    }
    void process(_ProcessorWrapper processor, Object record, boolean succeed) throws Exception{
        try {
            processor.method.invoke(_bean, record, succeed);
        }catch (Exception e){
            // 对异常进行转义处理
            if (e instanceof InvocationTargetException){
                Throwable throwable = e.getCause();
                if (throwable instanceof Exception){
                    throw (Exception)throwable;
                }
            }
            throw e;
        }
    }
}
